<!--
 * @Author: liaoxing
 * @Date: 2021-10-18 15:31:35
 * @LastEditors: liaoxing
 * @LastEditTime: 2021-11-04 14:04:27
 * @Description: liaoxing created
 * @FilePath: \pin-xin-admin\src\views\process\list\index.vue
-->
<template>
  <div class="process">
    <div class="leftBox">
      <div class="filterInputBox">
        <el-input
          placeholder="输入关键字进行过滤"
          v-model="filterText">
        </el-input>
      </div>

      <el-tree
        class="filter-tree"
        :data="categoryData"
        :props="defaultProps"
        :highlight-current="true"
        default-expand-all
        :filter-node-method="filterNode"
        @node-click ="treeNodeClick"
        ref="tree">
      </el-tree>
    </div>
    <div class="rightBox">
      <div class="searchBox">
        <span class="mlr20">关键词</span>
        <el-input
          placeholder="输入名称"
          v-model="keyWord">
        </el-input>
        <el-button type="primary" class="mlr20" @click="searchData">查询</el-button>
        <el-button type="primary" class="mlr20" @click="getList('reset')">重置</el-button>
        <el-button type="primary" class="mlr20 addBtn" @click="operateItem(false)">新增</el-button>
      </div>
      <div class="listBox">
        <el-table
          v-loading="loading"
          :data="listData"
          stripe
          border
          style="width: 100%;max-height: 660px">
          <el-table-column
            prop="name"
            label="名称"
            width="200">
          </el-table-column>
          <el-table-column
            prop="tag"
            label="标识"
            width="250">
          </el-table-column>
          <!-- <el-table-column
            prop="categoryName"
            width="200"
            label="分类名称">
          </el-table-column> -->
          <el-table-column
            prop="status"
            label="状态"
            width="160">
            <template slot-scope="scope">
              <el-tag size="small" :key="tagStatus[scope.row.status * 1 - 1].label" :type="tagStatus[scope.row.status * 1 - 1].type">{{ tagStatus[scope.row.status * 1 - 1].label }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column
            prop="changed"
            label="更新时间">
          </el-table-column>
          <el-table-column
            fixed="right"
            label="操作"
            width="200">
            <template slot-scope="scope">
              <el-tooltip class="item" effect="dark" content="流程图预览" placement="bottom">
                <span class="mlr5 finger" @click="procedurePreview(scope.row)">
                  <i class="el-icon-view font18"></i>
                </span>
              </el-tooltip>
              <el-tooltip v-if="scope.row.status === 2" class="item" effect="dark" content="发布" placement="bottom">
                <span class="mlr5 finger" @click="issue(scope.row)">
                  <i class="el-icon-s-promotion font18"></i>
                </span>
              </el-tooltip>
              <el-tooltip class="item" effect="dark" content="修改" placement="bottom">
                <span class="mlr5 finger" @click="operateItem(true, scope.row)">
                  <i class="el-icon-edit-outline font18"></i>
                </span>
              </el-tooltip>
              <el-tooltip v-if="scope.row.status !== 1 && scope.row.status !== 4" class="item" effect="dark" content="停用" placement="bottom">
                <span class="mlr5 finger" @click="stopProcess(scope.row)">
                  <i class="el-icon-error font18"></i>
                </span>
              </el-tooltip>
              <el-tooltip class="item" effect="dark" content="删除" placement="bottom">
                <span class="mlr5 finger">
                  <el-popconfirm
                    title="确定要删除该流程吗？"
                    @confirm="deleteItem(scope.row)"
                  >
                    <i slot="reference" class="el-icon-delete color-red font18"></i>
                  </el-popconfirm>
                </span>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          background
          style="float: right; margin-top: 20px"
          layout="prev, pager, next"
          @current-change="switchPage"
          :total="totleNum">
        </el-pagination>
      </div>
    </div>
    <el-dialog :visible.sync="dialogFormVisible" width="30%">
      <el-form :label-position="'right'" label-width="80px" :model="itemInfo" ref="itemInfo" :rules="rules">
        <el-form-item label="名称" prop="name">
          <el-input v-model.trim="itemInfo.name"></el-input>
        </el-form-item>
        <el-form-item label="标识" prop="tag">
          <el-input v-model.trim="itemInfo.tag" :disabled="isEdit"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm('itemInfo')">确定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
    <el-dialog :visible.sync="openXmlPreview" width="60%">
      <div ref="processBox" class="processBox" v-html="svgStr"></div>
    </el-dialog>
  </div>
</template>

<script>
import sessionStorage from "@/utils/sessionStorage"
import checkValue from "@/utils/checkCode"
import BpmnModeler from 'bpmn-js/lib/Modeler'
export default {
  name: 'process',
  data () {
    let checkCode = async (rule, value, callback) => {
      if (!value) {
        return callback(new Error('编码不能为空'));
      }
      let flag = await this.checkEntityExiste(value)
      if (!flag) {
        return callback(new Error('编码重复，请重新输入'));
      } else {
        let status = checkValue(value)
        if (!status) {
          callback()
          return
        }
        return callback(new Error(status));
      }
    }
    return {
      loading: false,
      filterText: '',
      keyWord: '',
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      categoryData: [],
      listData: [],
      pageSize: 10,
      pageNum: 1,
      totleNum: 0,
      dialogFormVisible: false,
      itemInfo: {
        name: "",
        tag: ""
      },
      rules: {
        name: [
          { required: true, message: '请输入流程名称', trigger: 'blur' },
        ],
        tag: [
          { required: true, validator: checkCode, trigger: 'blur' },
        ]
      },
      currentNode: null,
      tagStatus: [
        {type: "info", label: "草稿"},
        {type: "warning", label: "待发布"},
        {type: "success", label: "已发布"},
        {type: "danger", label: "停用"},
      ],
      isEdit: false,
      openXmlPreview: false,
      svgStr: ''
    }
  },
  async created () {
    await this.getCategoryTree()
    this.getList()
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    dialogFormVisible (value) {
      if (!value) {
        this.isEdit = false
        this.$refs["itemInfo"].clearValidate()
      }
    }
  },
  methods: {
    /* 预览流程 */
    createBoard(xml) {
      let processBoard = this.$refs.processBox
      // 建模
      this.bpmnModeler = new BpmnModeler({
        container: processBoard // 不需要容器，只要svg
      })
      this.createNewDiagram(xml)
    },
    /* 绘制xml */
    createNewDiagram(xml) {
      this.bpmnModeler.importXML(xml, (err) => {
        if (err) {
          this.$message.error("绘制失败")
        } else{
          this.bpmnModeler.saveSVG({ format: false }, (err, data) => {
            if (err) {
              this.$message.error("绘制失败")
            } else {
              console.log(data)
              let svgStr = data.replace(`<?xml version="1.0" encoding="utf-8"?>\n<!-- created with bpmn-js / http://bpmn.io -->\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">`, "")
              this.svgStr = svgStr
            }
          })
        }
      })
    },
    /* 节点过滤方法 */
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    /* 新增或修改 */
    operateItem (type, data) {
      if (!this.currentNode && !type) {
        this.$message.warning("请先选择分类类型！")
        return
      }
      this.dialogFormVisible = true
      if (type) { // 修改
        this.isEdit = true
        this.itemInfo = JSON.parse(JSON.stringify(data))
        return
      }
      this.itemInfo = {
        name: "",
        tag: ""
      }
    },
    /* 获取树 */
    getCategoryTree () {
      return new Promise((resolve, reject) => {
        this.$serve.getCategories({pageSize: 9999, pageNum: 1})
        .then(res => {
          if (res.code === 200) {
            this.categoryData = res.data.records
            resolve()
          } else {
            this.$message.error("请求异常！" + res.msg)
            reject()
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
          reject()
        })
      })
    },
    /* 搜索 */
    searchData () {
      if (!this.searchData) return
      this.getList()
    },
    /* 发布 */
    issue (item) {
      this.$serve.publishBpmn(item.id)
        .then(res => {
          if (res.code === 200) {
            this.$message.success("发布成功！")
            this.getList()
          } else {
            this.$message.error("请求异常！" + res.msg)
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
        })
    },
    /* 流程图预览 */
    procedurePreview (item) {
      this.openXmlPreview = true
      this.$serve.getByModelId(item.id)
        .then(res => {
          if (res.code === 200) {
            this.createBoard(res.data.modelXml)
          } else {
            this.$message.error("请求异常！" + res.msg)
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
        })
    },
    /* 停用 */
    stopProcess (item) {
      this.$serve.stopBpmn(item.id)
        .then(res => {
          if (res.code === 200) {
            this.$message.warning("停用成功！")
            this.getList()
          } else {
            this.$message.error("请求异常！" + res.msg)
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
        })
    },
    /* 删除流程 */
    deleteItem (item) {
      this.$serve.deleteByIds(item.id)
        .then(res => {
          if (res.code === 200) {
            this.getList()
          } else {
            this.$message.error("请求异常！" + res.msg)
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
        })
    },
    /* 切换页面 */
    switchPage (num) {
      this.pageNum = num
      this.getList()
    },
    /* 获取列表 */
    getList (type) {
      this.loading = true
      let params = {
        pageNum: this.pageNum,
        pageSize: this.pageSize
      }
      if (type === "reset") {
        this.currentNode = null
        this.keyWord = ''
      }
      if (this.currentNode && type != "reset") {
        params.categoryId = this.currentNode.id
      }
      if (this.keyWord && type != "reset") {
        params.keyWord = this.keyWord
      }
      this.$serve.getPagerModel(params)
      .then(res => {
        this.loading = false
        if (res.code === 200) {
          this.totleNum = res.data.total
          this.listData = res.data.records
        } else {
            this.$message.error("请求异常！" + res.msg)
          }
        })
        .catch(() => {
          this.$message.error("请求失败！" )
        })
    },
    /* 提交新增或者修改 */
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        console.log(this.itemInfo)
        if (valid) {
          let params = {
            categoryId: this.currentNode ? this.currentNode.id : this.itemInfo.categoryId,
            tag: this.itemInfo.tag,
            name: this.itemInfo.name
          }
          // if (this.itemInfo.id) {
          //   params.id = this.itemInfo.id
          // }
          this.$serve.saveOrUpdateModelInfo(params, this.isEdit, this.itemInfo.id)
            .then(res => {
              if (res.code === 200) {
                this.dialogFormVisible = false
                sessionStorage.set("currentModel", JSON.stringify({
                  id: res.data.id,
                  tag: res.data.tag,
                  name: res.data.name
                }))
                this.getList()
                this.$router.push('/process/createProcess')
              } else {
                  this.$message.error("请求异常！" + res.msg)
                }
            })
            .catch(() => {
              this.$message.error("请求失败！" )
            })
        } else {
          this.$message.error("提交失败" )
          return false;
        }
      });
    },
    /* 树节点点击 */
    treeNodeClick (data) {
      this.currentNode = data
      this.getList()
    },
    /* 检测编码是否重复 */
    checkEntityExiste (value) {
      if (this.isEdit) return true
      return new Promise((res) => {
        this.$serve.checkEntityExiste(value)
          .then(data => {
            res(data.code === 200 ? true :false)
          })
      })
    }
  }
}
</script>

<style lang="less">
.process{
  width: 100%;
  height: calc(100vh - 85px);
  box-sizing: border-box;
  padding: 20px;
  background-color: whitesmoke;
  .processBox{
    width: 100%;
    height: 700px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .leftBox, .searchBox, .listBox{
    background-color: white;
  }
  .leftBox{
    height: 100%;
    width: 260px;
    margin-right: 20px;
    float: left;
  }
  .rightBox{
    height: 100%;
    overflow: hidden;
    .searchBox{
      height: 60px;
      line-height: 60px;
      margin-bottom: 20px;
      position: relative;
      .el-input{
        width: 20%;
      }
      .addBtn{
        position: absolute;
        right: 0;
        top: 18px;
      }
    }
    .listBox{
      height: calc(100% - 60px);
      padding: 20px;
      box-sizing: border-box;
      overflow: auto;
    }
  }
  .filterInputBox{
    height: 60px;
    padding: 0 10px;
    line-height: 60px;
  }
}
</style>